Return to start page
common.ai
1 //==================================================================================================
2 // $Id: common.ai,v 1.68 2003/05/12 02:34:18 bfitch Exp $
3 //==================================================================================================
4 native DebugS takes string str returns nothing
5 native DebugFI takes string str, integer val returns nothing
6 native DebugUnitID takes string str, integer val returns nothing
7 native DisplayText takes integer p, string str returns nothing
8 native DisplayTextI takes integer p, string str, integer val returns nothing
9 native DisplayTextII takes integer p, string str, integer v1, integer v2 returns nothing
10 native DisplayTextIII takes integer p, string str, integer v1, integer v2, integer v3 returns nothing
11 native DoAiScriptDebug takes nothing returns boolean
12
13 native GetAiPlayer takes nothing returns integer
14 native GetHeroId takes nothing returns integer
15 native GetHeroLevelAI takes nothing returns integer
16
17 native GetUnitCount takes integer unitid returns integer
18 native GetPlayerUnitTypeCount takes player p, integer unitid returns integer
19 native GetUnitCountDone takes integer unitid returns integer
20 native GetTownUnitCount takes integer id, integer tn, boolean dn returns integer
21 native GetUnitGoldCost takes integer unitid returns integer
22 native GetUnitWoodCost takes integer unitid returns integer
23 native GetUnitBuildTime takes integer unitid returns integer
24
25 native GetMinesOwned takes nothing returns integer
26 native GetGoldOwned takes nothing returns integer
27 native TownWithMine takes nothing returns integer
28 native TownHasMine takes integer townid returns boolean
29 native TownHasHall takes integer townid returns boolean
30
31 native GetUpgradeLevel takes integer id returns integer
32 native GetUpgradeGoldCost takes integer id returns integer
33 native GetUpgradeWoodCost takes integer id returns integer
34 native GetNextExpansion takes nothing returns integer
35 native GetMegaTarget takes nothing returns unit
36 native GetBuilding takes player p returns unit
37 native GetEnemyPower takes nothing returns integer
38 native SetAllianceTarget takes unit id returns nothing
39 native GetAllianceTarget takes nothing returns unit
40
41 native SetProduce takes integer qty, integer id, integer town returns boolean
42 native Unsummon takes unit unitid returns nothing
43 native SetExpansion takes unit peon, integer id returns boolean
44 native SetUpgrade takes integer id returns boolean
45 native SetHeroLevels takes code func returns nothing
46 native SetNewHeroes takes boolean state returns nothing
47 native PurchaseZeppelin takes nothing returns nothing
48
49 native MergeUnits takes integer qty, integer a, integer b, integer make returns boolean
50 native ConvertUnits takes integer qty, integer id returns boolean
51
52 native SetCampaignAI takes nothing returns nothing
53 native SetMeleeAI takes nothing returns nothing
54 native SetTargetHeroes takes boolean state returns nothing
55 native SetPeonsRepair takes boolean state returns nothing
56 native SetRandomPaths takes boolean state returns nothing
57 native SetDefendPlayer takes boolean state returns nothing
58 native SetHeroesFlee takes boolean state returns nothing
59 native SetHeroesBuyItems takes boolean state returns nothing
60 native SetWatchMegaTargets takes boolean state returns nothing
61 native SetIgnoreInjured takes boolean state returns nothing
62 native SetHeroesTakeItems takes boolean state returns nothing
63 native SetUnitsFlee takes boolean state returns nothing
64 native SetGroupsFlee takes boolean state returns nothing
65 native SetSlowChopping takes boolean state returns nothing
66 native SetCaptainChanges takes boolean allow returns nothing
67 native SetSmartArtillery takes boolean state returns nothing
68 native SetReplacementCount takes integer qty returns nothing
69 native GroupTimedLife takes boolean allow returns nothing
70 native RemoveInjuries takes nothing returns nothing
71 native RemoveSiege takes nothing returns nothing
72
73 native InitAssault takes nothing returns nothing
74 native AddAssault takes integer qty, integer id returns boolean
75 native AddDefenders takes integer qty, integer id returns boolean
76
77 native GetCreepCamp takes integer min, integer max, boolean flyers_ok returns unit
78
79 native StartGetEnemyBase takes nothing returns nothing
80 native WaitGetEnemyBase takes nothing returns boolean
81 native GetEnemyBase takes nothing returns unit
82 native GetExpansionFoe takes nothing returns unit
83 native GetEnemyExpansion takes nothing returns unit
84 native GetExpansionX takes nothing returns integer
85 native GetExpansionY takes nothing returns integer
86 native SetStagePoint takes real x, real y returns nothing
87 native AttackMoveKill takes unit target returns nothing
88 native AttackMoveXY takes integer x, integer y returns nothing
89 native LoadZepWave takes integer x, integer y returns nothing
90 native SuicidePlayer takes player id, boolean check_full returns boolean
91 native SuicidePlayerUnits takes player id, boolean check_full returns boolean
92 native CaptainInCombat takes boolean attack_captain returns boolean
93 native IsTowered takes unit target returns boolean
94
95 native ClearHarvestAI takes nothing returns nothing
96 native HarvestGold takes integer town, integer peons returns nothing
97 native HarvestWood takes integer town, integer peons returns nothing
98 native GetExpansionPeon takes nothing returns unit
99
100 native StopGathering takes nothing returns nothing
101 native AddGuardPost takes integer id, real x, real y returns nothing
102 native FillGuardPosts takes nothing returns nothing
103 native ReturnGuardPosts takes nothing returns nothing
104 native CreateCaptains takes nothing returns nothing
105 native SetCaptainHome takes integer which, real x, real y returns nothing
106 native ResetCaptainLocs takes nothing returns nothing
107 native ShiftTownSpot takes real x, real y returns nothing
108 native TeleportCaptain takes real x, real y returns nothing
109 native ClearCaptainTargets takes nothing returns nothing
110 native CaptainAttack takes real x, real y returns nothing
111 native CaptainVsUnits takes player id returns nothing
112 native CaptainVsPlayer takes player id returns nothing
113 native CaptainGoHome takes nothing returns nothing
114 native CaptainIsHome takes nothing returns boolean
115 native CaptainIsFull takes nothing returns boolean
116 native CaptainIsEmpty takes nothing returns boolean
117 native CaptainGroupSize takes nothing returns integer
118 native CaptainReadiness takes nothing returns integer
119 native CaptainRetreating takes nothing returns boolean
120 native CaptainReadinessHP takes nothing returns integer
121 native CaptainReadinessMa takes nothing returns integer
122 native CaptainAtGoal takes nothing returns boolean
123 native CreepsOnMap takes nothing returns boolean
124 native SuicideUnit takes integer count, integer unitid returns nothing
125 native SuicideUnitEx takes integer ct, integer uid, integer pid returns nothing
126 native StartThread takes code func returns nothing
127 native Sleep takes real seconds returns nothing
128 native UnitAlive takes unit id returns boolean
129 native UnitInvis takes unit id returns boolean
130 native IgnoredUnits takes integer unitid returns integer
131 native TownThreatened takes nothing returns boolean
132 native DisablePathing takes nothing returns nothing
133 native SetAmphibious takes nothing returns nothing
134
135 native CommandsWaiting takes nothing returns integer
136 native GetLastCommand takes nothing returns integer
137 native GetLastData takes nothing returns integer
138 native PopLastCommand takes nothing returns nothing
139 native MeleeDifficulty takes nothing returns integer
140
141 //============================================================================
142 // Globals for all AI scripts
143 //============================================================================
144 globals
145
146 //--------------------------------------------------------------------
147 // HUMANS
148 //--------------------------------------------------------------------
149
150 // human heroes
151 constant integer ARCHMAGE = 'Hamg'
152 constant integer PALADIN = 'Hpal'
153 constant integer MTN_KING = 'Hmkg'
154 constant integer BLOOD_MAGE = 'Hblm'
155
156 // human hero abilities
157 constant integer AVATAR = 'AHav'
158 constant integer BASH = 'AHbh'
159 constant integer THUNDER_BOLT = 'AHtb'
160 constant integer THUNDER_CLAP = 'AHtc'
161
162 constant integer DEVOTION_AURA = 'AHad'
163 constant integer DIVINE_SHIELD = 'AHds'
164 constant integer HOLY_BOLT = 'AHhb'
165 constant integer RESURRECTION = 'AHre'
166
167 constant integer BLIZZARD = 'AHbz'
168 constant integer BRILLIANCE_AURA = 'AHab'
169 constant integer MASS_TELEPORT = 'AHmt'
170 constant integer WATER_ELEMENTAL = 'AHwe'
171
172 constant integer BANISH = 'AHbn'
173 constant integer FLAME_STRIKE = 'AHfs'
174 constant integer SUMMON_PHOENIX = 'AHpx'
175 constant integer SIPHON_MANA = 'AHdr'
176
177 // special human heroes
178 constant integer JAINA = 'Hjai'
179 constant integer MURADIN = 'Hmbr'
180 constant integer GARITHOS = 'Hlgr'
181 constant integer KAEL = 'Hkal'
182
183 // human units
184 constant integer COPTER = 'hgyr'
185 constant integer GYRO = COPTER
186 constant integer ELEMENTAL = 'hwat'
187 constant integer FOOTMAN = 'hfoo'
188 constant integer FOOTMEN = FOOTMAN
189 constant integer GRYPHON = 'hgry'
190 constant integer KNIGHT = 'hkni'
191 constant integer MORTAR = 'hmtm'
192 constant integer PEASANT = 'hpea'
193 constant integer PRIEST = 'hmpr'
194 constant integer RIFLEMAN = 'hrif'
195 constant integer RIFLEMEN = RIFLEMAN
196 constant integer SORCERESS = 'hsor'
197 constant integer TANK = 'hmtt'
198 constant integer STEAM_TANK = TANK
199 constant integer ROCKET_TANK = 'hrtt'
200 constant integer MILITIA = 'hmil'
201 constant integer SPELL_BREAKER = 'hspt'
202 constant integer HUMAN_DRAGON_HAWK = 'hdhw'
203
204 // special human units
205 constant integer BLOOD_PRIEST = 'hbep'
206 constant integer BLOOD_SORCERESS = 'hbes'
207 constant integer BLOOD_PEASANT = 'nhew'
208
209 // human buildings
210 constant integer AVIARY = 'hgra'
211 constant integer BARRACKS = 'hbar'
212 constant integer BLACKSMITH = 'hbla'
213 constant integer CANNON_TOWER = 'hctw'
214 constant integer CASTLE = 'hcas'
215 constant integer CHURCH = 'htws'
216 constant integer MAGE_TOWER = CHURCH
217 constant integer GUARD_TOWER = 'hgtw'
218 constant integer HOUSE = 'hhou'
219 constant integer HUMAN_ALTAR = 'halt'
220 constant integer KEEP = 'hkee'
221 constant integer LUMBER_MILL = 'hlum'
222 constant integer SANCTUM = 'hars'
223 constant integer ARCANE_SANCTUM = SANCTUM
224 constant integer TOWN_HALL = 'htow'
225 constant integer WATCH_TOWER = 'hwtw'
226 constant integer WORKSHOP = 'harm'
227 constant integer ARCANE_VAULT = 'hvlt'
228 constant integer ARCANE_TOWER = 'hatw'
229
230 // human upgrades
231 constant integer UPG_MELEE = 'Rhme'
232 constant integer UPG_RANGED = 'Rhra'
233 constant integer UPG_ARTILLERY = 'Rhaa'
234 constant integer UPG_ARMOR = 'Rhar'
235 constant integer UPG_GOLD = 'Rhmi'
236 constant integer UPG_MASONRY = 'Rhac'
237 constant integer UPG_SIGHT = 'Rhss'
238 constant integer UPG_DEFEND = 'Rhde'
239 constant integer UPG_BREEDING = 'Rhan'
240 constant integer UPG_PRAYING = 'Rhpt'
241 constant integer UPG_SORCERY = 'Rhst'
242 constant integer UPG_LEATHER = 'Rhla'
243 constant integer UPG_GUN_RANGE = 'Rhri'
244 constant integer UPG_WOOD = 'Rhlh'
245 constant integer UPG_SENTINEL = 'Rhse'
246 constant integer UPG_SCATTER = 'Rhsr'
247 constant integer UPG_BOMBS = 'Rhgb'
248 constant integer UPG_HAMMERS = 'Rhhb'
249 constant integer UPG_CONT_MAGIC = 'Rhss'
250 constant integer UPG_FRAGS = 'Rhfs'
251 constant integer UPG_TANK = 'Rhrt'
252 constant integer UPG_FLAK = 'Rhfc'
253 constant integer UPG_CLOUD = 'Rhcd'
254
255 //--------------------------------------------------------------------
256 // ORCS
257 //--------------------------------------------------------------------
258
259 // orc heroes
260 constant integer BLADE_MASTER = 'Obla'
261 constant integer FAR_SEER = 'Ofar'
262 constant integer TAUREN_CHIEF = 'Otch'
263 constant integer SHADOW_HUNTER = 'Oshd'
264
265 // special orc heroes
266 constant integer GROM = 'Ogrh'
267 constant integer THRALL = 'Othr'
268
269 // orc hero abilities
270 constant integer CRITICAL_STRIKE = 'AOcr'
271 constant integer MIRROR_IMAGE = 'AOmi'
272 constant integer BLADE_STORM = 'AOww'
273 constant integer WIND_WALK = 'AOwk'
274
275 constant integer CHAIN_LIGHTNING = 'AOcl'
276 constant integer EARTHQUAKE = 'AOeq'
277 constant integer FAR_SIGHT = 'AOfs'
278 constant integer SPIRIT_WOLF = 'AOsf'
279
280 constant integer ENDURANE_AURA = 'AOae'
281 constant integer REINCARNATION = 'AOre'
282 constant integer SHOCKWAVE = 'AOsh'
283 constant integer WAR_STOMP = 'AOws'
284
285 constant integer HEALING_WAVE = 'AOhw'
286 constant integer HEX = 'AOhx'
287 constant integer SERPENT_WARD = 'AOsw'
288 constant integer VOODOO = 'AOvd'
289
290 // orc units
291 constant integer GUARDIAN = 'oang'
292 constant integer CATAPULT = 'ocat'
293 constant integer WITCH_DOCTOR = 'odoc'
294 constant integer GRUNT = 'ogru'
295 constant integer HEAD_HUNTER = 'ohun'
296 constant integer BERSERKER = 'otbk'
297 constant integer KODO_BEAST = 'okod'
298 constant integer PEON = 'opeo'
299 constant integer RAIDER = 'orai'
300 constant integer SHAMAN = 'oshm'
301 constant integer TAUREN = 'otau'
302 constant integer WYVERN = 'owyv'
303 constant integer BATRIDER = 'otbr'
304 constant integer SPIRIT_WALKER = 'ospw'
305 constant integer SPIRIT_WALKER_M = 'ospm'
306
307 // orc buildings
308 constant integer ORC_ALTAR = 'oalt'
309 constant integer ORC_BARRACKS = 'obar'
310 constant integer BESTIARY = 'obea'
311 constant integer FORGE = 'ofor'
312 constant integer FORTRESS = 'ofrt'
313 constant integer GREAT_HALL = 'ogre'
314 constant integer LODGE = 'osld'
315 constant integer STRONGHOLD = 'ostr'
316 constant integer BURROW = 'otrb'
317 constant integer TOTEM = 'otto'
318 constant integer ORC_WATCH_TOWER = 'owtw'
319 constant integer VOODOO_LOUNGE = 'ovln'
320
321 // orc upgrades
322 constant integer UPG_ORC_MELEE = 'Rome'
323 constant integer UPG_ORC_RANGED = 'Rora'
324 constant integer UPG_ORC_ARTILLERY = 'Roaa'
325 constant integer UPG_ORC_ARMOR = 'Roar'
326 constant integer UPG_ORC_WAR_DRUMS = 'Rwdm'
327 constant integer UPG_ORC_PILLAGE = 'Ropg'
328 constant integer UPG_ORC_BERSERK = 'Robs'
329 constant integer UPG_ORC_PULVERIZE = 'Rows'
330 constant integer UPG_ORC_ENSNARE = 'Roen'
331 constant integer UPG_ORC_VENOM = 'Rovs'
332 constant integer UPG_ORC_DOCS = 'Rowd'
333 constant integer UPG_ORC_SHAMAN = 'Rost'
334 constant integer UPG_ORC_SPIKES = 'Rosp'
335 constant integer UPG_ORC_BURROWS = 'Rorb'
336 constant integer UPG_ORC_REGEN = 'Rotr'
337 constant integer UPG_ORC_FIRE = 'Rolf'
338 constant integer UPG_ORC_SWALKER = 'Rowt'
339 constant integer UPG_ORC_BERSERKER = 'Robk'
340 constant integer UPG_ORC_NAPTHA = 'Robf'
341 constant integer UPG_ORC_CHAOS = 'Roch'
342
343 // Warcraft 2 orc units
344 constant integer OGRE_MAGI = 'nomg'
345 constant integer ORC_DRAGON = 'nrwm'
346 constant integer SAPPER = 'ngsp'
347 constant integer ZEPPLIN = 'nzep'
348 constant integer ZEPPELIN = ZEPPLIN
349 constant integer W2_WARLOCK = 'nw2w'
350 constant integer PIG_FARM = 'npgf'
351
352 // special orc units
353 constant integer CHAOS_GRUNT = 'nchg'
354 constant integer CHAOS_WARLOCK = 'nchw'
355 constant integer CHAOS_RAIDER = 'nchr'
356 constant integer CHAOS_PEON = 'ncpn'
357 constant integer CHAOS_KODO = 'nckb'
358 constant integer CHAOS_GROM = 'Opgh'
359 constant integer CHAOS_BLADEMASTER = 'Nbbc'
360 constant integer CHAOS_BURROW = 'ocbw'
361
362 //--------------------------------------------------------------------
363 // UNDEAD
364 //--------------------------------------------------------------------
365
366 // undead heroes
367 constant integer DEATH_KNIGHT = 'Udea'
368 constant integer DREAD_LORD = 'Udre'
369 constant integer LICH = 'Ulic'
370 constant integer CRYPT_LORD = 'Ucrl'
371
372 // special undead heroes
373 constant integer MALGANIS = 'Umal'
374 constant integer TICHONDRIUS = 'Utic'
375 constant integer PIT_LORD = 'Npld'
376 constant integer DETHEROC = 'Udth'
377
378 // undead hero abilities
379 constant integer SLEEP = 'AUsl'
380 constant integer VAMP_AURA = 'AUav'
381 constant integer CARRION_SWARM = 'AUcs'
382 constant integer INFERNO = 'AUin'
383
384 constant integer DARK_RITUAL = 'AUdr'
385 constant integer DEATH_DECAY = 'AUdd'
386 constant integer FROST_ARMOR = 'AUfu'
387 constant integer FROST_NOVA = 'AUfn'
388
389 constant integer ANIM_DEAD = 'AUan'
390 constant integer DEATH_COIL = 'AUdc'
391 constant integer DEATH_PACT = 'AUdp'
392 constant integer UNHOLY_AURA = 'AUau'
393
394 constant integer CARRION_SCARAB = 'AUcb'
395 constant integer IMPALE = 'AUim'
396 constant integer LOCUST_SWARM = 'AUls'
397 constant integer THORNY_SHIELD = 'AUts'
398
399 // undead units
400 constant integer ABOMINATION = 'uabo'
401 constant integer ACOLYTE = 'uaco'
402 constant integer BANSHEE = 'uban'
403 constant integer PIT_FIEND = 'ucry'
404 constant integer CRYPT_FIEND = PIT_FIEND
405 constant integer FROST_WYRM = 'ufro'
406 constant integer GARGOYLE = 'ugar'
407 constant integer GARGOYLE_MORPH = 'ugrm'
408 constant integer GHOUL = 'ugho'
409 constant integer MEAT_WAGON = 'umtw'
410 constant integer NECRO = 'unec'
411 constant integer SKEL_WARRIOR = 'uske'
412 constant integer SHADE = 'ushd'
413 constant integer UNDEAD_BARGE = 'uarb'
414 constant integer OBSIDIAN_STATUE = 'uobs'
415 constant integer OBS_STATUE = OBSIDIAN_STATUE
416 constant integer BLK_SPHINX = 'ubsp'
417
418 // undead buildings
419 constant integer UNDEAD_MINE = 'ugol'
420 constant integer UNDEAD_ALTAR = 'uaod'
421 constant integer BONEYARD = 'ubon'
422 constant integer GARG_SPIRE = 'ugsp'
423 constant integer NECROPOLIS_1 = 'unpl' // normal
424 constant integer NECROPOLIS_2 = 'unp1' // upgraded once
425 constant integer NECROPOLIS_3 = 'unp2' // full upgrade
426 constant integer SAC_PIT = 'usap'
427 constant integer CRYPT = 'usep'
428 constant integer SLAUGHTERHOUSE = 'uslh'
429 constant integer DAMNED_TEMPLE = 'utod'
430 constant integer ZIGGURAT_1 = 'uzig' // normal
431 constant integer ZIGGURAT_2 = 'uzg1' // upgraded
432 constant integer ZIGGURAT_FROST = 'uzg2' // frost tower
433 constant integer GRAVEYARD = 'ugrv'
434 constant integer TOMB_OF_RELICS = 'utom'
435
436 // undead upgrades
437 constant integer UPG_UNHOLY_STR = 'Rume'
438 constant integer UPG_CR_ATTACK = 'Rura'
439 constant integer UPG_UNHOLY_ARMOR = 'Ruar'
440 constant integer UPG_CANNIBALIZE = 'Ruac'
441 constant integer UPG_GHOUL_FRENZY = 'Rugf'
442 constant integer UPG_FIEND_WEB = 'Ruwb'
443 constant integer UPG_ABOM = 'Ruab'
444 constant integer UPG_STONE_FORM = 'Rusf'
445 constant integer UPG_NECROS = 'Rune'
446 constant integer UPG_BANSHEE = 'Ruba'
447 constant integer UPG_MEAT_WAGON = 'Rump'
448 constant integer UPG_WYRM_BREATH = 'Rufb'
449 constant integer UPG_SKEL_LIFE = 'Rusl'
450 constant integer UPG_SKEL_MASTERY = 'Rusm'
451 constant integer UPG_EXHUME = 'Ruex'
452 constant integer UPG_SACRIFICE = 'Rurs'
453 constant integer UPG_ABOM_EXPL = 'Ruax'
454 constant integer UPG_CR_ARMOR = 'Rucr'
455 constant integer UPG_PLAGUE = 'Rupc'
456 constant integer UPG_BLK_SPHINX = 'Rusp'
457 constant integer UPG_BURROWING = 'Rubu'
458
459 //--------------------------------------------------------------------
460 // ELVES
461 //--------------------------------------------------------------------
462
463 // elf heroes
464 constant integer DEMON_HUNTER = 'Edem'
465 constant integer DEMON_HUNTER_M = 'Edmm'
466 constant integer KEEPER = 'Ekee'
467 constant integer MOON_CHICK = 'Emoo'
468 constant integer MOON_BABE = MOON_CHICK
469 constant integer MOON_HONEY = MOON_CHICK
470 constant integer WARDEN = 'Ewar'
471
472 // special elf heroes
473 constant integer SYLVANUS = 'Hvwd'
474 constant integer CENARIUS = 'Ecen'
475 constant integer ILLIDAN = 'Eevi'
476 constant integer ILLIDAN_DEMON = 'Eevm'
477 constant integer MAIEV = 'Ewrd'
478
479 // elf hero abilities
480 constant integer FORCE_NATURE = 'AEfn'
481 constant integer ENT_ROOTS = 'AEer'
482 constant integer THORNS_AURA = 'AEah'
483 constant integer TRANQUILITY = 'AEtq'
484
485 constant integer EVASION = 'AEev'
486 constant integer IMMOLATION = 'AEim'
487 constant integer MANA_BURN = 'AEmb'
488 constant integer METAMORPHOSIS = 'AEme'
489
490 constant integer SEARING_ARROWS = 'AHfa'
491 constant integer SCOUT = 'AEst'
492 constant integer STARFALL = 'AEsf'
493 constant integer TRUESHOT = 'AEar'
494
495 constant integer BLINK = 'AEbl'
496 constant integer FAN_KNIVES = 'AEfk'
497 constant integer SHADOW_TOUCH = 'AEsh'
498 constant integer VENGEANCE = 'AEsv'
499
500 // elf units
501 constant integer WISP = 'ewsp'
502 constant integer ARCHER = 'earc'
503 constant integer DRUID_TALON = 'edot'
504 constant integer DRUID_TALON_M = 'edtm'
505 constant integer BALLISTA = 'ebal'
506 constant integer DRUID_CLAW = 'edoc'
507 constant integer DRUID_CLAW_M = 'edcm'
508 constant integer DRYAD = 'edry'
509 constant integer HIPPO = 'ehip'
510 constant integer HIPPO_RIDER = 'ehpr'
511 constant integer HUNTRESS = 'esen'
512 constant integer CHIMAERA = 'echm'
513 constant integer ENT = 'efon'
514 constant integer MOUNTAIN_GIANT = 'emtg'
515 constant integer FAERIE_DRAGON = 'efdr'
516
517 // special elf units
518 constant integer HIGH_ARCHER = 'nhea'
519 constant integer HIGH_FOOTMAN = 'hcth'
520 constant integer HIGH_FOOTMEN = HIGH_FOOTMAN
521 constant integer HIGH_SWORDMAN = 'hhes'
522 constant integer DRAGON_HAWK = 'nws1'
523 constant integer CORRUPT_TREANT = 'nenc'
524 constant integer POISON_TREANT = 'nenp'
525 constant integer PLAGUE_TREANT = 'nepl'
526 constant integer SHANDRIS = 'eshd'
527
528 // elf buildings
529 constant integer ANCIENT_LORE = 'eaoe'
530 constant integer ANCIENT_WAR = 'eaom'
531 constant integer ANCIENT_WIND = 'eaow'
532 constant integer TREE_AGES = 'etoa'
533 constant integer TREE_ETERNITY = 'etoe'
534 constant integer TREE_LIFE = 'etol'
535 constant integer ANCIENT_PROTECT = 'etrp'
536 constant integer ELF_ALTAR = 'eate'
537 constant integer BEAR_DEN = 'edol'
538 constant integer CHIMAERA_ROOST = 'edos'
539 constant integer HUNTERS_HALL = 'edob'
540 constant integer MOON_WELL = 'emow'
541 constant integer ELF_MINE = 'egol'
542 constant integer DEN_OF_WONDERS = 'eden'
543
544 // special elf buildings
545 constant integer ELF_FARM = 'nefm'
546 constant integer ELF_GUARD_TOWER = 'negt'
547 constant integer HIGH_SKY = 'negm'
548 constant integer HIGH_EARTH = 'negf'
549 constant integer HIGH_TOWER = 'negt'
550 constant integer ELF_HIGH_BARRACKS = 'nheb'
551 constant integer CORRUPT_LIFE = 'nctl'
552 constant integer CORRUPT_WELL = 'ncmw'
553 constant integer CORRUPT_PROTECTOR = 'ncap'
554 constant integer CORRUPT_WAR = 'ncaw'
555
556 // elf upgrades
557 constant integer UPG_STR_MOON = 'Resm'
558 constant integer UPG_STR_WILD = 'Resw'
559 constant integer UPG_MOON_ARMOR = 'Rema'
560 constant integer UPG_HIDES = 'Rerh'
561 constant integer UPG_ULTRAVISION = 'Reuv'
562 constant integer UPG_BLESSING = 'Renb'
563 constant integer UPG_SCOUT = 'Resc'
564 constant integer UPG_GLAIVE = 'Remg'
565 constant integer UPG_BOWS = 'Reib'
566 constant integer UPG_MARKSMAN = 'Remk'
567 constant integer UPG_DRUID_TALON = 'Redt'
568 constant integer UPG_DRUID_CLAW = 'Redc'
569 constant integer UPG_ABOLISH = 'Resi'
570 constant integer UPG_CHIM_ACID = 'Recb'
571 constant integer UPG_HIPPO_TAME = 'Reht'
572 constant integer UPG_BOLT = 'Repd'
573 constant integer UPG_MARK_CLAW = 'Reeb'
574 constant integer UPG_MARK_TALON = 'Reec'
575 constant integer UPG_HARD_SKIN = 'Rehs'
576 constant integer UPG_RESIST_SKIN = 'Rers'
577 constant integer UPG_WELL_SPRING = 'Rews'
578
579 //--------------------------------------------------------------------
580 // Neutral
581 //--------------------------------------------------------------------
582 constant integer DEMON_GATE = 'ndmg'
583 constant integer FELLHOUND = 'nfel'
584 constant integer INFERNAL = 'ninf'
585 constant integer DOOMGUARD = 'nbal'
586 constant integer SATYR = 'nsty'
587 constant integer TRICKSTER = 'nsat'
588 constant integer SHADOWDANCER = 'nsts'
589 constant integer SOULSTEALER = 'nstl'
590 constant integer HELLCALLER = 'nsth'
591 constant integer SKEL_ARCHER = 'nska'
592 constant integer SKEL_MARKSMAN = 'nskm'
593 constant integer SKEL_BURNING = 'nskf'
594 constant integer SKEL_GIANT = 'nskg'
595 constant integer FURBOLG = 'nfrl'
596 constant integer FURBOLG_TRACKER = 'nfrb'
597 constant integer FURBOLG_SHAMAN = 'nfrs'
598 constant integer FURBOLG_CHAMP = 'nfrg'
599 constant integer FURBOLG_ELDER = 'nfre'
600
601 //--------------------------------------------------------------------
602 // NAGA
603 //--------------------------------------------------------------------
604
605 // naga heroes
606 constant integer NAGA_SORCERESS = 'Nngs'
607 constant integer NAGA_VASHJ = 'Hvsh'
608
609 // naga units
610 constant integer NAGA_DRAGON = 'nsnp' // old names
611 constant integer NAGA_WITCH = 'nnsw'
612 constant integer NAGA_SERPENT = 'nwgs'
613 constant integer NAGA_HYDRA = 'nhyc'
614
615 constant integer NAGA_SLAVE = 'nmpe' // peon
616 constant integer NAGA_SNAP_DRAGON = NAGA_DRAGON // weak ranged
617 constant integer NAGA_COUATL = NAGA_SERPENT // weak air
618 constant integer NAGA_SIREN = NAGA_WITCH // caster
619 constant integer NAGA_MYRMIDON = 'nmyr' // knight
620 constant integer NAGA_REAVER = 'nnmg' // footman
621 constant integer NAGA_TURTLE = NAGA_HYDRA // siege
622 constant integer NAGA_ROYAL = 'nnrg' // royal guard
623
624 // naga buildings
625 constant integer NAGA_TEMPLE = 'nntt' // town hall
626 constant integer NAGA_CORAL = 'nnfm' // farm
627 constant integer NAGA_SHRINE = 'nnsa' // sirens & couatls
628 constant integer NAGA_SPAWNING = 'nnsg' // myrm, snap dragon, hydra
629 constant integer NAGA_GUARDIAN = 'nntg' // tower
630 constant integer NAGA_ALTAR = 'nnad' // altar
631
632 // naga upgrades
633 constant integer UPG_NAGA_ARMOR = 'Rnam'
634 constant integer UPG_NAGA_ATTACK = 'Rnat'
635 constant integer UPG_NAGA_ABOLISH = 'Rnsi'
636 constant integer UPG_SIREN = 'Rnsw'
637 constant integer UPG_NAGA_ENSNARE = 'Rnen'
638
639
640 //--------------------------------------------------------------------
641 constant integer M1 = 60
642 constant integer M2 = 2*60
643 constant integer M3 = 3*60
644 constant integer M4 = 4*60
645 constant integer M5 = 5*60
646 constant integer M6 = 6*60
647 constant integer M7 = 7*60
648 constant integer M8 = 8*60
649 constant integer M9 = 9*60
650 constant integer M10 = 10*60
651 constant integer M11 = 11*60
652 constant integer M12 = 12*60
653 constant integer M13 = 13*60
654 constant integer M14 = 14*60
655 constant integer M15 = 15*60
656
657 constant integer EASY = 1
658 constant integer NORMAL = 2
659 constant integer HARD = 3
660 constant integer INSANE = 4 // not used
661
662 constant integer MELEE_NEWBIE = 1
663 constant integer MELEE_NORMAL = 2
664 constant integer MELEE_INSANE = 3
665
666 constant integer ATTACK_CAPTAIN = 1
667 constant integer DEFENSE_CAPTAIN = 2
668 constant integer BOTH_CAPTAINS = 3
669
670 constant integer BUILD_UNIT = 1
671 constant integer BUILD_UPGRADE = 2
672 constant integer BUILD_EXPAND = 3
673
674 constant integer UPKEEP_TIER1 = 50
675 constant integer UPKEEP_TIER2 = 80
676
677 //--------------------------------------------------------------------
678
679 player ai_player
680
681 integer sleep_seconds
682 integer total_gold = 0
683 integer total_wood = 0
684 integer gold_buffer = 0 // usually for potion money
685 integer difficulty = NORMAL
686 integer exp_seen = 0
687 integer racial_farm = 'hhou'
688 integer hero_id = 'Hamg'
689 integer hero_id2 = 'Hmkg'
690 integer hero_id3 = 'Hpal'
691 integer array skill
692 integer array skills1
693 integer array skills2
694 integer array skills3
695 integer max_hero_level = 0
696
697 integer array harass_qty
698 integer array harass_max
699 integer array harass_units
700 integer harass_length = 0
701
702 integer array defense_qty
703 integer array defense_units
704 integer defense_length = 0
705
706 integer array build_qty
707 integer array build_type
708 integer array build_item
709 integer array build_town
710 integer build_length = 0
711
712 integer campaign_gold_peons = 5
713 integer campaign_wood_peons = 3
714 integer campaign_basics_speed = 5
715
716 integer min_creeps = -1
717 integer max_creeps = -1
718
719 boolean harvest_town1 = true
720 boolean harvest_town2 = true
721 boolean harvest_town3 = true
722 boolean do_campaign_farms = true
723 boolean two_heroes = false
724 boolean allow_air_creeps = false
725 boolean take_exp = false
726 boolean allow_signal_abort = false
727 boolean ready_for_zeppelin = true
728 boolean get_zeppelin = false
729
730 boolean build_campaign_attackers = true
731
732 boolean do_debug_cheats = false
733 boolean trace_on = true
734 boolean zep_next_wave = false
735 boolean form_group_timeouts = true
736 endglobals
737
738 //============================================================================
739 function PlayerEx takes integer slot returns player
740 return Player(slot-1)
741 endfunction
742
743 //============================================================================
744 function Trace takes string message returns nothing
745 if trace_on then
746 call DisplayText(GetAiPlayer(),message)
747 endif
748 endfunction
749
750 //============================================================================
751 function TraceI takes string message, integer val returns nothing
752 if trace_on then
753 call DisplayTextI(GetAiPlayer(),message,val)
754 endif
755 endfunction
756
757 //============================================================================
758 function TraceII takes string message, integer v1, integer v2 returns nothing
759 if trace_on then
760 call DisplayTextII(GetAiPlayer(),message,v1,v2)
761 endif
762 endfunction
763
764 //============================================================================
765 function TraceIII takes string message, integer v1, integer v2, integer v3 returns nothing
766 if trace_on then
767 call DisplayTextIII(GetAiPlayer(),message,v1,v2,v3)
768 endif
769 endfunction
770
771 //============================================================================
772 function InitAI takes nothing returns nothing
773 set ai_player = Player(GetAiPlayer())
774 set sleep_seconds = 0
775 call StopGathering()
776 endfunction
777
778 //============================================================================
779 function StandardAI takes code heroes, code peons, code attacks returns nothing
780
781 local boolean isNewbie = (MeleeDifficulty() == MELEE_NEWBIE)
782
783 call InitAI()
784
785 call SetMeleeAI()
786
787 call SetDefendPlayer(true)
788 call SetGroupsFlee(not isNewbie)
789 call SetHeroesBuyItems(not isNewbie)
790 call SetHeroesFlee(true)
791 call SetHeroesTakeItems(true)
792 call SetIgnoreInjured(true)
793 call SetPeonsRepair(true)
794 call SetSmartArtillery(not isNewbie)
795 call SetTargetHeroes(not isNewbie)
796 call SetUnitsFlee(not isNewbie)
797 call SetWatchMegaTargets(true)
798
799 call CreateCaptains()
800
801 call SetHeroLevels(heroes)
802
803 call Sleep(0.1)
804 call StartThread(peons)
805 call StartThread(attacks)
806 endfunction
807
808 //============================================================================
809 // Utility Functions
810 //============================================================================
811 function Min takes integer A, integer B returns integer
812 if A < B then
813 return A
814 else
815 return B
816 endif
817 endfunction
818
819 function Max takes integer A, integer B returns integer
820 if A > B then
821 return A
822 else
823 return B
824 endif
825 endfunction
826
827 function SetZepNextWave takes nothing returns nothing
828 set zep_next_wave = true
829 endfunction
830
831 function SuicideSleep takes integer seconds returns nothing
832 set sleep_seconds = sleep_seconds - seconds
833 loop
834 exitwhen seconds <= 0
835 exitwhen allow_signal_abort and CommandsWaiting() != 0
836
837 if seconds >= 5 then
838 call Sleep(5)
839 set seconds = seconds - 5
840 else
841 call Sleep(seconds)
842 set seconds = 0
843 endif
844 endloop
845 endfunction
846
847 //============================================================================
848 function WaitForSignal takes nothing returns integer
849 local integer cmd
850 local boolean display = false //xxx
851 loop
852 exitwhen CommandsWaiting() != 0
853
854 //xxx
855 call Trace("waiting for a signal to begin AI script...\n")
856 set display = true
857 call Sleep(2)
858 exitwhen CommandsWaiting() != 0
859 call Sleep(2)
860 exitwhen CommandsWaiting() != 0
861 call Sleep(2)
862 exitwhen CommandsWaiting() != 0
863 call Sleep(2)
864 exitwhen CommandsWaiting() != 0
865 call Sleep(2)
866 //xxx
867
868 endloop
869
870 //xxx
871 if display then
872 call Trace("signal received, beginning AI script\n")
873 endif
874 //xxx
875
876 set cmd = GetLastCommand()
877 call PopLastCommand()
878 return cmd
879 endfunction
880
881 //============================================================================
882 function SetWoodPeons takes integer count returns nothing
883 set campaign_wood_peons = count
884 endfunction
885
886 //============================================================================
887 function SetGoldPeons takes integer count returns nothing
888 set campaign_gold_peons = count
889 endfunction
890
891 //============================================================================
892 function SetHarvestLumber takes boolean harvest returns nothing
893 if harvest then
894 set campaign_wood_peons = 3
895 else
896 set campaign_wood_peons = 0
897 endif
898 endfunction
899
900 //============================================================================
901 function SetFormGroupTimeouts takes boolean state returns nothing
902 set form_group_timeouts = state
903 endfunction
904
905 //============================================================================
906 function DoCampaignFarms takes boolean state returns nothing
907 set do_campaign_farms = state
908 endfunction
909
910 //============================================================================
911 function GetMinorCreep takes nothing returns unit
912 return GetCreepCamp(0,9,false)
913 endfunction
914
915 //============================================================================
916 function GetMajorCreep takes nothing returns unit
917 return GetCreepCamp(10,100,allow_air_creeps)
918 endfunction
919
920 //============================================================================
921 function GetGold takes nothing returns integer
922 return GetPlayerState(ai_player,PLAYER_STATE_RESOURCE_GOLD)
923 endfunction
924
925 //============================================================================
926 function GetWood takes nothing returns integer
927 return GetPlayerState(ai_player,PLAYER_STATE_RESOURCE_LUMBER)
928 endfunction
929
930 //============================================================================
931 function InitBuildArray takes nothing returns nothing
932 set build_length = 0
933 endfunction
934
935 //============================================================================
936 function InitAssaultGroup takes nothing returns nothing
937 set harass_length = 0
938 endfunction
939
940 //============================================================================
941 function InitDefenseGroup takes nothing returns nothing
942 set defense_length = 0
943 endfunction
944
945 //============================================================================
946 function InitMeleeGroup takes nothing returns nothing
947 call InitAssaultGroup()
948 call RemoveInjuries()
949 call RemoveSiege()
950 endfunction
951
952 //============================================================================
953 function PrepFullSuicide takes nothing returns nothing
954 call InitAssaultGroup()
955 call InitDefenseGroup()
956 set campaign_gold_peons = 0
957 set campaign_wood_peons = 0
958 endfunction
959
960 //============================================================================
961 function SetReplacements takes integer easy, integer med, integer hard returns nothing
962 if difficulty == EASY then
963 call SetReplacementCount(easy)
964 elseif difficulty == NORMAL then
965 call SetReplacementCount(med)
966 else
967 call SetReplacementCount(hard)
968 endif
969 endfunction
970
971 //============================================================================
972 function StartTownBuilder takes code func returns nothing
973 call StartThread(func)
974 endfunction
975
976 //============================================================================
977 function SetBuildAll takes integer t, integer qty, integer unitid, integer town returns nothing
978 if qty > 0 then
979 set build_qty[build_length] = qty
980 set build_type[build_length] = t
981 set build_item[build_length] = unitid
982 set build_town[build_length] = town
983 set build_length = build_length + 1
984 endif
985 endfunction
986
987 //============================================================================
988 function SetBuildUnit takes integer qty, integer unitid returns nothing
989 call SetBuildAll(BUILD_UNIT,qty,unitid,-1)
990 endfunction
991
992 //============================================================================
993 function SetBuildNext takes integer qty, integer unitid returns nothing
994 local integer has = GetUnitCount(unitid)
995 if has >= qty then
996 return
997 endif
998 call SetBuildAll(BUILD_UNIT,GetUnitCountDone(unitid)+1,unitid,-1)
999 endfunction
1000
1001 //============================================================================
1002 function SetBuildUnitEx takes integer easy, integer med, integer hard, integer unitid returns nothing
1003 if difficulty == EASY then
1004 call SetBuildAll(BUILD_UNIT,easy,unitid,-1)
1005 elseif difficulty == NORMAL then
1006 call SetBuildAll(BUILD_UNIT,med,unitid,-1)
1007 else
1008 call SetBuildAll(BUILD_UNIT,hard,unitid,-1)
1009 endif
1010 endfunction
1011
1012 //============================================================================
1013 function SecondaryTown takes integer town, integer qty, integer unitid returns nothing
1014 call SetBuildAll(BUILD_UNIT,qty,unitid,town)
1015 endfunction
1016
1017 //============================================================================
1018 function SecTown takes integer town, integer qty, integer unitid returns nothing
1019 call SetBuildAll(BUILD_UNIT,qty,unitid,town)
1020 endfunction
1021
1022 //============================================================================
1023 function SetBuildUpgr takes integer qty, integer unitid returns nothing
1024 if MeleeDifficulty() != MELEE_NEWBIE or qty == 1 then
1025 call SetBuildAll(BUILD_UPGRADE,qty,unitid,-1)
1026 endif
1027 endfunction
1028
1029 //============================================================================
1030 function SetBuildUpgrEx takes integer easy, integer med, integer hard, integer unitid returns nothing
1031 if difficulty == EASY then
1032 call SetBuildAll(BUILD_UPGRADE,easy,unitid,-1)
1033 elseif difficulty == NORMAL then
1034 call SetBuildAll(BUILD_UPGRADE,med,unitid,-1)
1035 else
1036 call SetBuildAll(BUILD_UPGRADE,hard,unitid,-1)
1037 endif
1038 endfunction
1039
1040 //============================================================================
1041 function SetBuildExpa takes integer qty, integer unitid returns nothing
1042 call SetBuildAll(BUILD_EXPAND,qty,unitid,-1)
1043 endfunction
1044
1045 //============================================================================
1046 function StartUpgrade takes integer level, integer upgid returns boolean
1047 local integer gold_cost
1048 local integer wood_cost
1049
1050 if GetUpgradeLevel(upgid) >= level then
1051 return true
1052 endif
1053
1054 set gold_cost = GetUpgradeGoldCost(upgid)
1055 if total_gold < gold_cost then
1056 return false
1057 endif
1058
1059 set wood_cost = GetUpgradeWoodCost(upgid)
1060 if total_wood < wood_cost then
1061 return false
1062 endif
1063
1064 return SetUpgrade(upgid)
1065 endfunction
1066
1067 //============================================================================
1068 function BuildFactory takes integer unitid returns nothing
1069 if GetGold() > 1000 and GetWood() > 500 then
1070 call SetBuildUnit( 2, unitid )
1071 else
1072 call SetBuildUnit( 1, unitid )
1073 endif
1074 endfunction
1075
1076 //============================================================================
1077 function HallsCompleted takes integer unitid returns boolean
1078 return GetUnitCount(unitid) == GetUnitCountDone(unitid)
1079 endfunction
1080
1081 //============================================================================
1082 function GuardSecondary takes integer townid, integer qty, integer unitid returns nothing
1083 if TownHasHall(townid) and TownHasMine(townid) then
1084 call SecondaryTown( townid, qty, unitid )
1085 endif
1086 endfunction
1087
1088 //============================================================================
1089 function GetUnitCountEx takes integer unitid, boolean only_done, integer townid returns integer
1090 if townid == -1 then
1091 if only_done then
1092 return GetUnitCountDone(unitid)
1093 else
1094 return GetUnitCount(unitid)
1095 endif
1096 else
1097 return GetTownUnitCount(unitid,townid,only_done)
1098 endif
1099 endfunction
1100
1101 //============================================================================
1102 function TownCountEx takes integer unitid, boolean only_done, integer townid returns integer
1103
1104 local integer have_qty = GetUnitCountEx(unitid,only_done,townid)
1105
1106 if unitid == TOWN_HALL then
1107 set have_qty = have_qty + GetUnitCountEx(KEEP,false,townid) + GetUnitCountEx(CASTLE,false,townid)
1108 elseif unitid == KEEP then
1109 set have_qty = have_qty + GetUnitCountEx(CASTLE,false,townid)
1110
1111 elseif unitid == WATCH_TOWER then
1112 set have_qty = have_qty + GetUnitCountEx(GUARD_TOWER,false,townid) + GetUnitCountEx(CANNON_TOWER,false,townid) + GetUnitCountEx(ARCANE_TOWER,false,townid)
1113
1114 elseif unitid == PEASANT then
1115 set have_qty = have_qty + GetUnitCountEx(MILITIA,false,townid)
1116
1117 elseif unitid == GREAT_HALL then
1118 set have_qty = have_qty + GetUnitCountEx(STRONGHOLD,false,townid) + GetUnitCountEx(FORTRESS,false,townid)
1119 elseif unitid == STRONGHOLD then
1120 set have_qty = have_qty + GetUnitCountEx(FORTRESS,false,townid)
1121
1122 elseif unitid == HEAD_HUNTER then
1123 set have_qty = have_qty + GetUnitCountEx(BERSERKER,false,townid)
1124
1125 elseif unitid == SPIRIT_WALKER then
1126 set have_qty = have_qty + GetUnitCountEx(SPIRIT_WALKER_M,false,townid)
1127 elseif unitid == SPIRIT_WALKER_M then
1128 set have_qty = have_qty + GetUnitCountEx(SPIRIT_WALKER,only_done,townid)
1129
1130 elseif unitid == NECROPOLIS_1 then
1131 set have_qty = have_qty + GetUnitCountEx(NECROPOLIS_2,false,townid) + GetUnitCountEx(NECROPOLIS_3,false,townid)
1132 elseif unitid == NECROPOLIS_2 then
1133 set have_qty = have_qty + GetUnitCountEx(NECROPOLIS_3,false,townid)
1134
1135 elseif unitid == ZIGGURAT_1 then
1136 set have_qty = have_qty + GetUnitCountEx(ZIGGURAT_2,false,townid) + GetUnitCountEx(ZIGGURAT_FROST,false,townid)
1137
1138 elseif unitid == GARGOYLE then
1139 set have_qty = have_qty + GetUnitCountEx(GARGOYLE_MORPH,false,townid)
1140
1141 elseif unitid == TREE_LIFE then
1142 set have_qty = have_qty + GetUnitCountEx(TREE_AGES,false,townid) + GetUnitCountEx(TREE_ETERNITY,false,townid)
1143 elseif unitid == TREE_AGES then
1144 set have_qty = have_qty + GetUnitCountEx(TREE_ETERNITY,false,townid)
1145
1146 elseif unitid == DRUID_TALON then
1147 set have_qty = have_qty + GetUnitCountEx(DRUID_TALON_M,false,townid)
1148 elseif unitid == DRUID_TALON_M then
1149 set have_qty = have_qty + GetUnitCountEx(DRUID_TALON,only_done,townid)
1150
1151 elseif unitid == DRUID_CLAW then
1152 set have_qty = have_qty + GetUnitCountEx(DRUID_CLAW_M,false,townid)
1153 elseif unitid == DRUID_CLAW_M then
1154 set have_qty = have_qty + GetUnitCountEx(DRUID_CLAW,only_done,townid)
1155
1156 elseif unitid == ILLIDAN then
1157 set have_qty = have_qty + GetUnitCountEx(ILLIDAN_DEMON,false,townid)
1158
1159 endif
1160 return have_qty
1161 endfunction
1162
1163 //============================================================================
1164 function TownCountDone takes integer base returns integer
1165 return TownCountEx(base,true,-1)
1166 endfunction
1167
1168 //============================================================================
1169 function TownCount takes integer base returns integer
1170 return TownCountEx(base,false,-1)
1171 endfunction
1172
1173 //============================================================================
1174 function BasicExpansion takes boolean build_it, integer unitid returns nothing
1175 if build_it and HallsCompleted(unitid) then
1176 call SetBuildExpa( TownCount(unitid)+1, unitid )
1177 endif
1178 endfunction
1179
1180 //============================================================================
1181 function UpgradeAll takes integer baseid, integer newid returns nothing
1182 call SetBuildUnit( TownCountDone(baseid), newid )
1183 endfunction
1184
1185 //============================================================================
1186 function TownCountTown takes integer base, integer townid returns integer
1187 return TownCountEx(base,false,townid)
1188 endfunction
1189
1190 //============================================================================
1191 // FoodPool
1192 //============================================================================
1193 function FoodPool takes integer food, boolean weak, integer id1, integer use1, boolean strong, integer id2, integer use2 returns nothing
1194 if strong then
1195 call SetBuildUnit( (food - use1 * TownCount(id1)) / use2, id2 )
1196 elseif weak then
1197 call SetBuildUnit( (food - use2 * TownCount(id2)) / use1, id1 )
1198 endif
1199 endfunction
1200
1201 //============================================================================
1202 // MeleeTownHall
1203 //============================================================================
1204 function MeleeTownHall takes integer townid, integer unitid returns nothing
1205 if TownHasMine(townid) and not TownHasHall(townid) then
1206 call SecondaryTown ( townid, 1, unitid )
1207 endif
1208 endfunction
1209
1210 //============================================================================
1211 function WaitForUnits takes integer unitid, integer qty returns nothing
1212 loop
1213 exitwhen TownCountDone(unitid) == qty
1214 call Sleep(2)
1215 endloop
1216 endfunction
1217
1218 //============================================================================
1219 function StartUnit takes integer ask_qty, integer unitid, integer town returns boolean
1220 local integer have_qty
1221 local integer need_qty
1222 local integer afford_gold
1223 local integer afford_wood
1224 local integer afford_qty
1225 local integer gold_cost
1226 local integer wood_cost
1227
1228 //------------------------------------------------------------------------
1229 // if we have all we're asking for then make nothing
1230 //
1231 if town == -1 then
1232 set have_qty = TownCount(unitid)
1233 else
1234 set have_qty = TownCountTown(unitid,town)
1235 endif
1236
1237 if have_qty >= ask_qty then
1238 return true
1239 endif
1240 set need_qty = ask_qty - have_qty
1241
1242 //------------------------------------------------------------------------
1243 // limit the qty we're requesting to the amount of resources available
1244 //
1245 set gold_cost = GetUnitGoldCost(unitid)
1246 set wood_cost = GetUnitWoodCost(unitid)
1247
1248 if gold_cost == 0 then
1249 set afford_gold = need_qty
1250 else
1251 set afford_gold = total_gold / gold_cost
1252 endif
1253 if afford_gold < need_qty then
1254 set afford_qty = afford_gold
1255 else
1256 set afford_qty = need_qty
1257 endif
1258
1259 if wood_cost == 0 then
1260 set afford_wood = need_qty
1261 else
1262 set afford_wood = total_wood / wood_cost
1263 endif
1264 if afford_wood < afford_qty then
1265 set afford_qty = afford_wood
1266 endif
1267
1268 // if we're waiting on gold/wood; pause build orders
1269 if afford_qty < 1 then
1270 return false
1271 endif
1272
1273 //------------------------------------------------------------------------
1274 // whether we make right now what we're requesting or not, assume we will
1275 // and deduct the cost of the units from our fake gold total right away
1276 //
1277 set total_gold = total_gold - gold_cost * need_qty
1278 set total_wood = total_wood - wood_cost * need_qty
1279
1280 if total_gold < 0 then
1281 set total_gold = 0
1282 endif
1283 if total_wood < 0 then
1284 set total_wood = 0
1285 endif
1286
1287 //------------------------------------------------------------------------
1288 // give the AI a chance to make the units (it may not be able to right now
1289 // but that doesn't stop us from trying other units after this as long
1290 // as we have enough money to make this AND the needed, unbuilt ones)
1291 //
1292 return SetProduce(afford_qty,unitid,town)
1293 endfunction
1294
1295 //============================================================================
1296 function WaitForTown takes integer towns, integer townid returns nothing
1297 local integer i = 0
1298 loop
1299 call Sleep(10)
1300 exitwhen TownCount(townid) >= towns
1301 set i = i + 1
1302 exitwhen i == 12
1303 endloop
1304 endfunction
1305
1306 //============================================================================
1307 function StartExpansion takes integer qty, integer hall returns boolean
1308 local integer count
1309 local integer town
1310 local unit peon
1311 local integer gold_cost
1312
1313 set count = TownCount(hall)
1314 if count >= qty then
1315 return true
1316 endif
1317
1318 set town = GetNextExpansion()
1319 if town == -1 then
1320 return true
1321 endif
1322
1323 set take_exp = true
1324
1325 set gold_cost = GetUnitGoldCost(hall)
1326 if gold_cost > total_gold then
1327 return false
1328 endif
1329 set total_gold = total_gold - gold_cost
1330
1331 if GetExpansionFoe() != null then
1332 return true
1333 endif
1334
1335 set peon = GetExpansionPeon()
1336 if peon != null then
1337 return SetExpansion(peon,hall)
1338 endif
1339
1340 return true
1341 endfunction
1342
1343 //============================================================================
1344 function OneBuildLoop takes nothing returns nothing
1345 local integer index = 0
1346 local integer qty
1347 local integer id
1348 local integer tp
1349
1350 set total_gold = GetGold() - gold_buffer
1351 set total_wood = GetWood()
1352
1353 loop
1354 exitwhen index == build_length
1355
1356 set qty = build_qty [index]
1357 set id = build_item[index]
1358 set tp = build_type[index]
1359
1360 //--------------------------------------------------------------------
1361 if tp == BUILD_UNIT then
1362 if not StartUnit(qty,id,build_town[index]) then
1363 return
1364 endif
1365
1366 //--------------------------------------------------------------------
1367 elseif tp == BUILD_UPGRADE then
1368 call StartUpgrade(qty,id)
1369
1370 //--------------------------------------------------------------------
1371 else // tp == BUILD_EXPAND
1372 if not StartExpansion(qty,id) then
1373 return
1374 endif
1375 endif
1376
1377 set index = index + 1
1378 endloop
1379 endfunction
1380
1381 //============================================================================
1382 function StaggerSleep takes real base, real spread returns nothing
1383 call Sleep(base + spread * I2R(GetAiPlayer()) / I2R(GetPlayers()))
1384 endfunction
1385
1386 //============================================================================
1387 function BuildLoop takes nothing returns nothing
1388 call OneBuildLoop()
1389 call StaggerSleep(1,2)
1390 loop
1391 call OneBuildLoop()
1392 call Sleep(2)
1393 endloop
1394 endfunction
1395
1396 //============================================================================
1397 function StartBuildLoop takes nothing returns nothing
1398 call StartThread(function BuildLoop)
1399 endfunction
1400
1401 //============================================================================
1402 function SetInitialWave takes integer seconds returns nothing
1403 set sleep_seconds = seconds
1404 endfunction
1405
1406 //============================================================================
1407 function AddSleepSeconds takes integer seconds returns nothing
1408 set sleep_seconds = sleep_seconds + seconds
1409 endfunction
1410
1411 //============================================================================
1412 function SleepForever takes nothing returns nothing
1413 call Trace("going to sleep forever\n") //xxx
1414 loop
1415 call Sleep(100)
1416 endloop
1417 endfunction
1418
1419 //============================================================================
1420 function PlayGame takes nothing returns nothing
1421 call StartBuildLoop()
1422 call SleepForever()
1423 endfunction
1424
1425 //============================================================================
1426 function ConvertNeeds takes integer unitid returns nothing
1427 if GetUnitCount(unitid) < 1 then
1428 call StartUnit(1,unitid,-1)
1429 endif
1430 endfunction
1431
1432 //============================================================================
1433 function Conversions takes integer desire, integer unitid returns nothing
1434
1435 if GetUnitCount(unitid) >= desire then
1436 return
1437 endif
1438
1439 if unitid == HIPPO_RIDER then
1440 call ConvertNeeds(ARCHER)
1441 call ConvertNeeds(HIPPO)
1442 call MergeUnits(desire,ARCHER,HIPPO,HIPPO_RIDER)
1443
1444 elseif unitid == BLK_SPHINX then
1445 call ConvertNeeds(OBS_STATUE)
1446 call ConvertUnits(desire,OBS_STATUE)
1447 endif
1448 endfunction
1449
1450 //============================================================================
1451 function SetAssaultGroup takes integer qty, integer max, integer unitid returns nothing
1452 call Conversions(max,unitid)
1453
1454 if qty <= 0 and TownCountDone(unitid) == 0 then
1455 return
1456 endif
1457 set harass_qty[harass_length] = qty
1458 set harass_max[harass_length] = max
1459 set harass_units[harass_length] = unitid
1460 set harass_length = harass_length + 1
1461 endfunction
1462
1463 //============================================================================
1464 function Interleave3 takes integer e1, integer m1, integer h1, integer u1, integer e2, integer m2, integer h2, integer u2, integer e3, integer m3, integer h3, integer u3 returns nothing
1465 local integer i1 = 1
1466 local integer i2 = 1
1467 local integer i3 = 1
1468 local integer q1
1469 local integer q2
1470 local integer q3
1471
1472 if difficulty == EASY then
1473 set q1 = e1
1474 set q2 = e2
1475 set q3 = e3
1476 elseif difficulty == NORMAL then
1477 set q1 = m1
1478 set q2 = m2
1479 set q3 = m3
1480 else // difficulty == HARD
1481 set q1 = h1
1482 set q2 = h2
1483 set q3 = h3
1484 endif
1485
1486 loop
1487 exitwhen q1<=0 and q2<=0 and q3<=0
1488
1489 if q1 > 0 then
1490 call SetAssaultGroup(i1,i1,u1)
1491 set q1 = q1 - 1
1492 set i1 = i1 + 1
1493 endif
1494
1495 if q2 > 0 then
1496 call SetAssaultGroup(i2,i2,u2)
1497 set q2 = q2 - 1
1498 set i2 = i2 + 1
1499 endif
1500
1501 if q3 > 0 then
1502 call SetAssaultGroup(i3,i3,u3)
1503 set q3 = q3 - 1
1504 set i3 = i3 + 1
1505 endif
1506 endloop
1507 endfunction
1508
1509 //============================================================================
1510 function SetMeleeGroup takes integer unitid returns nothing
1511 if unitid == hero_id then
1512 call SetAssaultGroup(1,9,unitid)
1513 else
1514 call SetAssaultGroup((TownCountDone(unitid)*3)/4,20,unitid)
1515 endif
1516 endfunction
1517
1518 //============================================================================
1519 function CampaignDefender takes integer level, integer qty, integer unitid returns nothing
1520 if qty > 0 and difficulty >= level then
1521 set defense_qty[defense_length] = qty
1522 set defense_units[defense_length] = unitid
1523 set defense_length = defense_length + 1
1524 call Conversions(qty,unitid)
1525 call SetBuildUnit(qty,unitid)
1526 endif
1527 endfunction
1528
1529 //============================================================================
1530 function CampaignDefenderEx takes integer easy, integer med, integer hard, integer unitid returns nothing
1531 if difficulty == EASY then
1532 call CampaignDefender(EASY,easy,unitid)
1533 elseif difficulty == NORMAL then
1534 call CampaignDefender(NORMAL,med,unitid)
1535 else
1536 call CampaignDefender(HARD,hard,unitid)
1537 endif
1538 endfunction
1539
1540 //============================================================================
1541 function CampaignAttacker takes integer level, integer qty, integer unitid returns nothing
1542 if qty > 0 and difficulty >= level then
1543 call SetAssaultGroup(qty,qty,unitid)
1544 endif
1545 endfunction
1546
1547 //============================================================================
1548 function CampaignAttackerEx takes integer easy, integer med, integer hard, integer unitid returns nothing
1549 if difficulty == EASY then
1550 call CampaignAttacker(EASY,easy,unitid)
1551 elseif difficulty == NORMAL then
1552 call CampaignAttacker(NORMAL,med,unitid)
1553 else
1554 call CampaignAttacker(HARD,hard,unitid)
1555 endif
1556 endfunction
1557
1558 //============================================================================
1559 function FormGroup takes integer seconds, boolean testReady returns nothing
1560 local integer index
1561 local integer count
1562 local integer unitid
1563 local integer desire
1564 local integer readyPercent
1565
1566 // normally test for CaptainReadiness() of 50%
1567 if testReady == true then
1568 set readyPercent = 50
1569 call Trace("forming group, requiring healthy guys\n") //xxx
1570 else
1571 set readyPercent = 0
1572 call Trace("forming group, unit health not important\n") //xxx
1573 endif
1574
1575 call Trace("trying to gather forces\n") //xxx
1576
1577 loop
1578 call SuicideSleep(seconds)
1579 call InitAssault()
1580
1581 set index = 0
1582 loop
1583 exitwhen index == harass_length
1584
1585 set unitid = harass_units[index]
1586 set desire = harass_max[index]
1587 set count = TownCountDone(unitid)
1588
1589 call Conversions(desire,unitid)
1590
1591 if count >= desire then
1592 call AddAssault(desire,unitid)
1593 else
1594 set desire = harass_qty[index]
1595
1596 if count < desire then
1597 call AddAssault(desire,unitid)
1598 else
1599 call AddAssault(count,unitid)
1600 endif
1601 endif
1602
1603 set index = index + 1
1604 endloop
1605
1606 //xxx
1607 if form_group_timeouts and (sleep_seconds < -60) then
1608 call Trace("exit form group -- timeout\n")
1609 elseif CaptainInCombat(true) then
1610 call Trace("exit form group -- can't form while already in combat\n")
1611 elseif CaptainIsFull() and CaptainReadiness() >= readyPercent then
1612 call Trace("exit form group -- ready\n")
1613 endif
1614 //xxx
1615
1616 // time out and send group anyway if time has already expired
1617 exitwhen form_group_timeouts and (sleep_seconds < -60)
1618 exitwhen CaptainInCombat(true)
1619 exitwhen CaptainIsFull() and CaptainReadiness() >= readyPercent
1620 endloop
1621 endfunction
1622
1623 //============================================================================
1624 function WavePrepare takes integer unitid returns integer
1625 return GetUnitBuildTime(unitid)
1626 endfunction
1627
1628 //============================================================================
1629 function PrepTime takes nothing returns integer
1630 local integer unitid
1631 local integer missing
1632 local integer prep
1633 local integer count
1634 local integer largest = 30
1635 local integer index = 0
1636
1637 loop
1638 exitwhen index == harass_length
1639
1640 set unitid = harass_units[index]
1641 set missing = harass_qty[index] + IgnoredUnits(unitid) - TownCount(unitid)
1642 set prep = WavePrepare(unitid) * missing
1643
1644 if prep > largest then
1645 set largest = prep
1646 endif
1647
1648 set index = index + 1
1649 endloop
1650 call TraceI("next wave will require around %d seconds to build and gather\n",largest) //xxx
1651
1652 return largest
1653 endfunction
1654
1655 //============================================================================
1656 function PrepSuicideOnPlayer takes integer seconds returns boolean
1657 local integer wave_prep = PrepTime()
1658 local integer save_length
1659
1660 set save_length = harass_length
1661 set harass_length = 0
1662
1663 call AddSleepSeconds(seconds)
1664 if sleep_seconds-wave_prep > 0 then
1665 call TraceI("going to sleep for %d seconds before gathering next attack wave\n",sleep_seconds-wave_prep) //xxx
1666 call SuicideSleep(sleep_seconds-wave_prep)
1667 endif
1668
1669 call Trace("preparing suicide attack wave\n") //xxx
1670
1671 set harass_length = save_length
1672 if harass_length < 1 then
1673 call Trace("ERROR - no units specificed, exiting early\n") //xxx
1674 return false
1675 endif
1676
1677 return true
1678 endfunction
1679
1680 //============================================================================
1681 function SleepUntilAtGoal takes nothing returns nothing
1682 loop
1683 exitwhen CaptainRetreating()
1684 exitwhen CaptainAtGoal() // reached goal
1685 exitwhen CaptainIsHome() // failed to path and returned home
1686 exitwhen CaptainIsEmpty() // all units died
1687 call SuicideSleep(3)
1688 endloop
1689 endfunction
1690
1691 //============================================================================
1692 function SleepInCombat takes nothing returns nothing
1693 local integer count = 0
1694 debug call Trace("SleepInCombat\n")
1695 loop
1696 loop
1697 exitwhen not CaptainInCombat(true) // goal is cleared
1698 exitwhen CaptainIsEmpty() // duh
1699 call SuicideSleep(1)
1700 endloop
1701
1702 set count = count + 1
1703 exitwhen count >= 8
1704
1705 //xxx this is what it should have been; do this for next patch?
1706 //call SuicideSleep(1)
1707 endloop
1708 debug call Trace("exit SleepInCombat\n")
1709 endfunction
1710
1711 //============================================================================
1712 function AttackMoveXYA takes integer x, integer y returns nothing
1713
1714 if zep_next_wave then
1715 call LoadZepWave(x,y)
1716 set zep_next_wave = false
1717 endif
1718
1719 call AttackMoveXY(x,y)
1720 call SleepUntilAtGoal()
1721 call SleepInCombat()
1722 endfunction
1723
1724 //============================================================================
1725 function SuicideOnPlayerWave takes nothing returns nothing
1726 call Trace("waiting for attack wave to enter combat\n") //xxx
1727 loop
1728 //xxx
1729 if allow_signal_abort and CommandsWaiting() != 0 then
1730 call Trace("ABORT -- attack wave override\n")
1731 endif
1732
1733 if CaptainInCombat(true) then
1734 call Trace("done - captain has entered combat\n")
1735 endif
1736
1737 if CaptainIsEmpty() then
1738 call Trace("done - all units are dead\n")
1739 endif
1740
1741 if sleep_seconds < -300 then
1742 call Trace("done - timeout, took too long to reach engage the enemy\n")
1743 endif
1744 //xxx
1745
1746 exitwhen allow_signal_abort and CommandsWaiting() != 0
1747
1748 exitwhen CaptainInCombat(true)
1749 exitwhen CaptainIsEmpty()
1750 call SuicideSleep(10)
1751 exitwhen sleep_seconds < -300
1752 endloop
1753
1754 call Trace("waiting for attack wave to die\n") //xxx
1755 loop
1756 //xxx
1757 if allow_signal_abort and CommandsWaiting() != 0 then
1758 call Trace("ABORT - attack wave override\n")
1759 endif
1760
1761 if CaptainIsEmpty() then
1762 call Trace("done - all units are dead\n")
1763 endif
1764
1765 if sleep_seconds < -300 then
1766 call Trace("done - timeout, took too long to reach engage the enemy\n")
1767 endif
1768 //xxx
1769
1770 exitwhen allow_signal_abort and CommandsWaiting() != 0
1771
1772 exitwhen CaptainIsEmpty()
1773 call SuicideSleep(10)
1774 exitwhen sleep_seconds < -300
1775 endloop
1776 endfunction
1777
1778 //--------------------------------------------------------------------------------------------------
1779 function CommonSuicideOnPlayer takes boolean standard, boolean bldgs, integer seconds, player p, integer x, integer y returns nothing
1780 local integer save_peons
1781
1782 if not PrepSuicideOnPlayer(seconds) then
1783 return
1784 endif
1785
1786 set save_peons = campaign_wood_peons
1787 set campaign_wood_peons = 0
1788
1789 loop
1790 //xxx
1791 if allow_signal_abort and CommandsWaiting() != 0 then
1792 call Trace("ABORT -- attack wave override\n")
1793 endif
1794 //xxx
1795
1796 exitwhen allow_signal_abort and CommandsWaiting() != 0
1797
1798 loop
1799 exitwhen allow_signal_abort and CommandsWaiting() != 0
1800
1801 call FormGroup(5,true)
1802 exitwhen sleep_seconds <= 0
1803 call TraceI("waiting %d seconds before suicide\n",sleep_seconds) //xxx
1804 endloop
1805
1806 if standard then
1807 if bldgs then
1808 exitwhen SuicidePlayer(p,sleep_seconds >= -60)
1809 else
1810 exitwhen SuicidePlayerUnits(p,sleep_seconds >= -60)
1811 endif
1812 else
1813 call AttackMoveXYA(x,y)
1814 endif
1815
1816 call TraceI("waiting %d seconds before timeout\n",60+sleep_seconds) //xxx
1817 call SuicideSleep(5)
1818 endloop
1819
1820 set campaign_wood_peons = save_peons
1821 set harass_length = 0
1822
1823 call SuicideOnPlayerWave()
1824 endfunction
1825
1826 //--------------------------------------------------------------------------------------------------
1827 function SuicideOnPlayer takes integer seconds, player p returns nothing
1828 call CommonSuicideOnPlayer(true,true,seconds,p,0,0)
1829 endfunction
1830
1831 //--------------------------------------------------------------------------------------------------
1832 function SuicideOnUnits takes integer seconds, player p returns nothing
1833 call CommonSuicideOnPlayer(true,false,seconds,p,0,0)
1834 endfunction
1835
1836 //--------------------------------------------------------------------------------------------------
1837 function SuicideOnPoint takes integer seconds, player p, integer x, integer y returns nothing
1838 call CommonSuicideOnPlayer(false,false,seconds,p,x,y)
1839 endfunction
1840
1841 //============================================================================
1842 function SuicideUntilSignal takes integer seconds, player p returns nothing
1843 local integer save
1844 local integer wave_prep = PrepTime()
1845
1846 loop
1847 call AddSleepSeconds(seconds)
1848 if sleep_seconds-wave_prep > 0 then
1849 call SuicideSleep(sleep_seconds-wave_prep)
1850 endif
1851
1852 set save = campaign_wood_peons
1853 set campaign_wood_peons = 0
1854 loop
1855 loop
1856 call FormGroup(5, true)
1857 exitwhen sleep_seconds <= 0
1858 exitwhen CommandsWaiting() != 0
1859 endloop
1860 exitwhen SuicidePlayer(p,sleep_seconds >= -60)
1861 exitwhen CommandsWaiting() != 0
1862 call SuicideSleep(3)
1863 endloop
1864 set campaign_wood_peons = save
1865
1866 loop
1867 exitwhen CaptainIsEmpty()
1868 exitwhen CommandsWaiting() != 0
1869 call SuicideSleep(5)
1870 endloop
1871 exitwhen CommandsWaiting() != 0
1872 endloop
1873 endfunction
1874
1875 //--------------------------------------------------------------------------------------------------
1876 function SuicideOnce takes integer easy, integer med, integer hard, integer unitid returns nothing
1877 if difficulty == EASY then
1878 call SuicideUnit(easy,unitid)
1879 elseif difficulty == NORMAL then
1880 call SuicideUnit(med,unitid)
1881 else
1882 call SuicideUnit(hard,unitid)
1883 endif
1884 endfunction
1885
1886 //--------------------------------------------------------------------------------------------------
1887 function SuicideUnitA takes integer unitid returns nothing
1888 if unitid != 0 then
1889 call SuicideUnit(1,unitid)
1890 endif
1891 call Sleep(0.1)
1892 endfunction
1893
1894 //--------------------------------------------------------------------------------------------------
1895 function SuicideUnitB takes integer unitid, integer playerid returns nothing
1896 if unitid != 0 then
1897 call SuicideUnitEx(1,unitid,playerid)
1898 endif
1899 call Sleep(0.1)
1900 endfunction
1901
1902 //--------------------------------------------------------------------------------------------------
1903 function SuicideUnits takes integer u1, integer u2, integer u3, integer u4, integer u5, integer u6, integer u7, integer u8, integer u9, integer uA returns nothing
1904 call Trace("MASS SUICIDE - this script is now technically done\n") //xxx
1905
1906 call PrepFullSuicide()
1907 loop
1908 call SuicideUnitA(u1)
1909 call SuicideUnitA(u2)
1910 call SuicideUnitA(u3)
1911 call SuicideUnitA(u4)
1912 call SuicideUnitA(u5)
1913 call SuicideUnitA(u6)
1914 call SuicideUnitA(u7)
1915 call SuicideUnitA(u8)
1916 call SuicideUnitA(u9)
1917 call SuicideUnitA(uA)
1918 endloop
1919 endfunction
1920
1921 //--------------------------------------------------------------------------------------------------
1922 function SuicideUnitsEx takes integer playerid, integer u1, integer u2, integer u3, integer u4, integer u5, integer u6, integer u7, integer u8, integer u9, integer uA returns nothing
1923 call Trace("MASS SUICIDE - this script is now technically done\n") //xxx
1924
1925 call PrepFullSuicide()
1926 loop
1927 call SuicideUnitB(u1,playerid)
1928 call SuicideUnitB(u2,playerid)
1929 call SuicideUnitB(u3,playerid)
1930 call SuicideUnitB(u4,playerid)
1931 call SuicideUnitB(u5,playerid)
1932 call SuicideUnitB(u6,playerid)
1933 call SuicideUnitB(u7,playerid)
1934 call SuicideUnitB(u8,playerid)
1935 call SuicideUnitB(u9,playerid)
1936 call SuicideUnitB(uA,playerid)
1937 endloop
1938 endfunction
1939
1940 //--------------------------------------------------------------------------------------------------
1941 function SuicideOnPlayerEx takes integer easy, integer med, integer hard, player p returns nothing
1942 if difficulty == EASY then
1943 call SuicideOnPlayer(easy,p)
1944 elseif difficulty == NORMAL then
1945 call SuicideOnPlayer(med,p)
1946 else
1947 call SuicideOnPlayer(hard,p)
1948 endif
1949 endfunction
1950
1951 //--------------------------------------------------------------------------------------------------
1952 function SuicideOnUnitsEx takes integer easy, integer med, integer hard, player p returns nothing
1953 if difficulty == EASY then
1954 call SuicideOnUnits(easy,p)
1955 elseif difficulty == NORMAL then
1956 call SuicideOnUnits(med,p)
1957 else
1958 call SuicideOnUnits(hard,p)
1959 endif
1960 endfunction
1961
1962 //--------------------------------------------------------------------------------------------------
1963 function SuicideOnPointEx takes integer easy, integer med, integer hard, player p, integer x, integer y returns nothing
1964 if difficulty == EASY then
1965 call SuicideOnPoint(easy,p,x,y)
1966 elseif difficulty == NORMAL then
1967 call SuicideOnPoint(med,p,x,y)
1968 else
1969 call SuicideOnPoint(hard,p,x,y)
1970 endif
1971 endfunction
1972
1973 //============================================================================
1974 function ForeverSuicideOnPlayer takes integer seconds, player p returns nothing
1975 local integer length = harass_length
1976 loop
1977 exitwhen allow_signal_abort and CommandsWaiting() != 0
1978 call SuicideOnPlayer(seconds,p)
1979 set harass_length = length
1980 endloop
1981 endfunction
1982
1983 //============================================================================
1984 function CommonSleepUntilTargetDead takes unit target, boolean reform returns nothing
1985 loop
1986 exitwhen CaptainRetreating()
1987 exitwhen CaptainReadinessHP() <= 40
1988
1989 exitwhen not UnitAlive(target)
1990 exitwhen UnitInvis(target) and not IsUnitDetected(target,ai_player)
1991
1992 if not TownThreatened() then
1993 call AttackMoveKill(target)
1994 endif
1995
1996 call SuicideSleep(3)
1997
1998 if reform and sleep_seconds < -40 then
1999 if CaptainInCombat(true) then
2000 set sleep_seconds = sleep_seconds + 5
2001 else
2002 set sleep_seconds = 0
2003 call FormGroup(1,false)
2004 endif
2005 endif
2006 endloop
2007 endfunction
2008
2009 //============================================================================
2010 function SleepUntilTargetDead takes unit target returns nothing
2011 call CommonSleepUntilTargetDead(target,false)
2012 endfunction
2013
2014 //============================================================================
2015 function ReformUntilTargetDead takes unit target returns nothing
2016 debug call Trace("ReformUntilTargetDead\n")
2017 call CommonSleepUntilTargetDead(target,true)
2018 endfunction
2019
2020 //============================================================================
2021 function AttackMoveKillA takes unit target returns nothing
2022 if target == null then
2023 call SuicideSleep(3)
2024 return
2025 endif
2026
2027 debug call Trace("AttackMoveKillA\n")
2028 call AttackMoveKill(target)
2029 call ReformUntilTargetDead(target)
2030 call SleepInCombat()
2031 endfunction
2032
2033 //============================================================================
2034 function MinorCreepAttack takes nothing returns nothing
2035 local unit target = GetMinorCreep()
2036 call SetAllianceTarget(target)
2037 call FormGroup(3, true)
2038 call AttackMoveKillA(target)
2039 endfunction
2040
2041 //============================================================================
2042 function MajorCreepAttack takes nothing returns nothing
2043 local unit target = GetMajorCreep()
2044 call SetAllianceTarget(target)
2045 call FormGroup(3,true)
2046 call AttackMoveKillA(target)
2047 endfunction
2048
2049 //============================================================================
2050 function CreepAttackEx takes nothing returns nothing
2051 local unit target = GetCreepCamp(min_creeps,max_creeps,allow_air_creeps)
2052 call SetAllianceTarget(target)
2053 call FormGroup(3,true)
2054 call AttackMoveKillA(target)
2055 endfunction
2056
2057 //============================================================================
2058 function AnyPlayerAttack takes nothing returns nothing
2059 local unit hall
2060
2061 set hall = GetEnemyExpansion()
2062 if hall == null then
2063 call StartGetEnemyBase()
2064 loop
2065 exitwhen not WaitGetEnemyBase()
2066 call SuicideSleep(1)
2067 endloop
2068 set hall = GetEnemyBase()
2069 endif
2070
2071 call SetAllianceTarget(hall)
2072 call FormGroup(3,true)
2073 call AttackMoveKillA(hall)
2074 endfunction
2075
2076 //============================================================================
2077 function ExpansionAttack takes nothing returns nothing
2078 local unit creep = GetExpansionFoe()
2079 local integer x
2080
2081 call FormGroup(3, true)
2082 if creep == null then
2083 set x = GetExpansionX()
2084 if x != -1 then
2085 call AttackMoveXYA(x,GetExpansionY())
2086 endif
2087 else
2088 call AttackMoveKillA(creep)
2089 endif
2090 endfunction
2091
2092 //============================================================================
2093 // AddSiege
2094 //============================================================================
2095 function AddSiege takes nothing returns nothing
2096 call SetAssaultGroup( 0, 9, SHADE )
2097 call SetAssaultGroup( 0, 9, MEAT_WAGON )
2098 call SetAssaultGroup( 0, 9, MORTAR )
2099 call SetAssaultGroup( 0, 9, TANK )
2100 call SetAssaultGroup( 0, 9, BALLISTA )
2101 call SetAssaultGroup( 0, 9, CATAPULT )
2102 endfunction
2103
2104 //===========================================================================
2105 // GetAllyCount
2106 //============================================================================
2107 function GetAllyCount takes player whichPlayer returns integer
2108 local integer playerIndex = 0
2109 local integer count = 0
2110 local player indexPlayer
2111
2112 loop
2113 set indexPlayer = Player(playerIndex)
2114
2115 if whichPlayer != indexPlayer then
2116 if GetPlayerAlliance(whichPlayer,indexPlayer,ALLIANCE_PASSIVE) then
2117 if GetPlayerAlliance(indexPlayer,whichPlayer,ALLIANCE_PASSIVE) then
2118 if GetPlayerStructureCount(indexPlayer,true) > 0 then
2119 set count = count + 1
2120 endif
2121 endif
2122 endif
2123 endif
2124
2125 set playerIndex = playerIndex + 1
2126 exitwhen playerIndex == 12
2127 endloop
2128
2129 return count
2130 endfunction
2131
2132 //============================================================================
2133 // SingleMeleeAttack
2134 //============================================================================
2135 function SingleMeleeAttack takes boolean needs_exp, boolean has_siege, boolean major_ok, boolean air_units returns nothing
2136 local boolean can_siege
2137 local real daytime
2138 local unit hall
2139 local unit mega
2140 local unit creep
2141 local unit common
2142 local integer minimum
2143 local boolean allies
2144
2145 call Trace("===SingleMeleeAttack===\n") //xxx
2146
2147 if TownThreatened() then
2148 call Trace("sleep 2, town threatened\n") //xxx
2149 call Sleep(2)
2150 return
2151 endif
2152
2153 // purchase zeppelins
2154 //
2155 if get_zeppelin and GetGold() > 300 and GetWood() > 100 then
2156 call Trace("purchase zep\n") //xxx
2157 call PurchaseZeppelin()
2158 set get_zeppelin = false
2159 set ready_for_zeppelin = false
2160 return
2161 endif
2162 set ready_for_zeppelin = true
2163
2164 // coordinate with allies
2165 //
2166 set allies = GetAllyCount(ai_player) > 0
2167 if allies and MeleeDifficulty() != MELEE_NEWBIE then
2168 set common = GetAllianceTarget()
2169 if common != null then
2170 call Trace("join ally force\n") //xxx
2171 if GetMegaTarget() != null then
2172 call AddSiege()
2173 endif
2174 call FormGroup(3,true)
2175 call AttackMoveKillA(common)
2176 call SetAllianceTarget(null)
2177 return
2178 endif
2179 endif
2180
2181 // take expansions as needed
2182 //
2183 if needs_exp then
2184 call Trace("needs exp\n") //xxx
2185 set creep = GetExpansionFoe()
2186 if creep != null then
2187 call Trace("attack exp\n") //xxx
2188 call SetAllianceTarget(creep)
2189 call FormGroup(3,true)
2190 call AttackMoveKillA(creep)
2191 call Sleep(20)
2192 set take_exp = false
2193 return
2194 endif
2195 endif
2196
2197 // all-out attack if the player is weak
2198 //
2199 if MeleeDifficulty() != MELEE_NEWBIE then
2200 set mega = GetMegaTarget()
2201 if mega != null then
2202 call Trace("MEGA TARGET!!!\n") //xxx
2203 call AddSiege()
2204 call FormGroup(3,true)
2205 call AttackMoveKillA(mega)
2206 return
2207 endif
2208 endif
2209
2210 // deny player an expansion
2211 //
2212 set hall = GetEnemyExpansion()
2213 set daytime = GetFloatGameState(GAME_STATE_TIME_OF_DAY)
2214 set can_siege = has_siege and (air_units or (daytime>=4 and daytime<=12))
2215
2216 if hall!=null and (can_siege or not IsTowered(hall)) then
2217
2218 call Trace("test player town attack\n") //xxx
2219
2220 if MeleeDifficulty() == MELEE_NEWBIE then
2221 set minimum = 3
2222 elseif allies and MeleeDifficulty() == MELEE_NORMAL then
2223 set minimum = 1
2224 else
2225 set minimum = 0 // HARD, INSANE, and NORMAL with no allies
2226 endif
2227
2228 if exp_seen >= minimum then
2229 call Trace("do player town attack\n") //xxx
2230 set exp_seen = 0
2231 call AddSiege()
2232 call SetAllianceTarget(hall)
2233 call FormGroup(3,true)
2234 call AttackMoveKillA(hall)
2235 return
2236 endif
2237
2238 set exp_seen = exp_seen + 1
2239 endif
2240
2241 // attack player's main base when siege is available
2242 //
2243 if can_siege then
2244 call Trace("attack player's town\n") //xxx
2245 call AddSiege()
2246 call AnyPlayerAttack()
2247 return
2248 endif
2249
2250 // extended, more specific method of determining creep levels
2251 //
2252 if min_creeps != -1 then
2253 call TraceI("custom creep attack %d\n",max_creeps) //xxx
2254 call CreepAttackEx()
2255 return
2256 endif
2257
2258 // nothing better to do, so kill a creep camp
2259 //
2260 if major_ok then
2261 call Trace("major creep attack\n") //xxx
2262 call MajorCreepAttack()
2263 return
2264 endif
2265
2266 call Trace("minor creep attack\n") //xxx
2267 call MinorCreepAttack()
2268 endfunction
2269
2270 //============================================================================
2271 function GetZeppelin takes nothing returns nothing
2272 if ready_for_zeppelin then
2273 set get_zeppelin = true
2274 endif
2275 endfunction
2276
2277 //============================================================================
2278 function FoodUsed takes nothing returns integer
2279 return GetPlayerState(ai_player,PLAYER_STATE_RESOURCE_FOOD_USED)
2280 endfunction
2281
2282 //============================================================================
2283 function FoodCap takes nothing returns integer
2284 return GetPlayerState(ai_player,PLAYER_STATE_RESOURCE_FOOD_CAP)
2285 endfunction
2286
2287 //============================================================================
2288 function FoodSpace takes nothing returns integer
2289 return FoodCap() - FoodUsed()
2290 endfunction
2291
2292 //============================================================================
2293 function FoodAvail takes integer base returns integer
2294 return GetFoodMade(racial_farm) * TownCount(racial_farm) + GetFoodMade(base) * TownCount(base)
2295 endfunction
2296
2297 //============================================================================
2298 function BuildAttackers takes nothing returns nothing
2299 local integer index = 0
2300 local integer unitid
2301 local integer desire
2302 local integer count
2303
2304 loop
2305 exitwhen index == harass_length
2306
2307 set unitid = harass_units[index]
2308 set desire = harass_qty[index] + IgnoredUnits(unitid)
2309 set count = TownCount(unitid)
2310
2311 if count != desire then
2312 if not StartUnit(desire,unitid,-1) then
2313 return
2314 endif
2315 endif
2316
2317 set index = index + 1
2318 endloop
2319 endfunction
2320
2321 //============================================================================
2322 function BuildDefenders takes nothing returns nothing
2323 local integer index = 0
2324 local integer unitid
2325 local integer qty
2326 loop
2327 exitwhen index == defense_length
2328
2329 set unitid = defense_units[index]
2330 set qty = defense_qty[index]
2331
2332 call Conversions(qty,unitid)
2333 call AddDefenders(qty,unitid)
2334
2335 set index = index + 1
2336 endloop
2337 endfunction
2338
2339 //============================================================================
2340 function CampaignBasicsA takes nothing returns nothing
2341 local integer food_each = GetFoodMade(racial_farm)
2342 local integer on_wood
2343
2344 call ClearHarvestAI()
2345
2346 if CaptainInCombat(false) then
2347 set on_wood = 0
2348 else
2349 set on_wood = campaign_wood_peons
2350 endif
2351
2352 call HarvestGold(0,campaign_gold_peons)
2353 call HarvestWood(0,on_wood)
2354
2355 if harvest_town1 then
2356 call HarvestGold(1,campaign_gold_peons)
2357 call HarvestWood(1,on_wood)
2358 endif
2359
2360 if harvest_town2 then
2361 call HarvestGold(2,campaign_gold_peons)
2362 call HarvestWood(2,on_wood)
2363 endif
2364
2365 if harvest_town3 then
2366 call HarvestGold(3,campaign_gold_peons)
2367 call HarvestWood(3,on_wood)
2368 endif
2369
2370 if do_campaign_farms and FoodUsed()+food_each-1 > food_each*(TownCount(racial_farm)+1) then
2371 call StartUnit(TownCount(racial_farm)+1,racial_farm,-1)
2372 endif
2373
2374 if build_campaign_attackers then
2375 call BuildAttackers()
2376 endif
2377
2378 if not CaptainInCombat(false) then
2379 call BuildDefenders()
2380 endif
2381
2382 call FillGuardPosts()
2383 call ReturnGuardPosts()
2384 endfunction
2385
2386 //============================================================================
2387 function CampaignBasics takes nothing returns nothing
2388 call Sleep(1)
2389 call CampaignBasicsA()
2390 call StaggerSleep(1,5)
2391 loop
2392 call CampaignBasicsA()
2393 call Sleep(campaign_basics_speed)
2394 endloop
2395 endfunction
2396
2397 //============================================================================
2398 function CampaignAI takes integer farms, code heroes returns nothing
2399 if GetGameDifficulty() == MAP_DIFFICULTY_EASY then
2400 set difficulty = EASY
2401
2402 call SetTargetHeroes(false)
2403 call SetUnitsFlee(false)
2404
2405 elseif GetGameDifficulty() == MAP_DIFFICULTY_NORMAL then
2406 set difficulty = NORMAL
2407
2408 call SetTargetHeroes(false)
2409 call SetUnitsFlee(false)
2410
2411 elseif GetGameDifficulty() == MAP_DIFFICULTY_HARD then
2412 set difficulty = HARD
2413
2414 call SetPeonsRepair(true)
2415 else
2416 set difficulty = INSANE
2417 endif
2418
2419 call InitAI()
2420 call InitBuildArray()
2421 call InitAssaultGroup()
2422 call CreateCaptains()
2423
2424 call SetNewHeroes(false)
2425 if heroes != null then
2426 call SetHeroLevels(heroes)
2427 endif
2428
2429 call SetHeroesFlee(false)
2430 call SetGroupsFlee(false)
2431 call SetSlowChopping(true)
2432 call GroupTimedLife(false)
2433 call SetCampaignAI()
2434 call Sleep(0.1)
2435
2436 set racial_farm = farms
2437 call StartThread(function CampaignBasics)
2438 call StartBuildLoop()
2439 endfunction
2440
2441 //============================================================================
2442 function UnsummonAll takes nothing returns nothing
2443 local unit bldg
2444 loop
2445 set bldg = GetBuilding(ai_player)
2446 exitwhen bldg==null
2447 call Unsummon(bldg)
2448 call Sleep(2)
2449 endloop
2450 endfunction
2451
2452 //============================================================================
2453 // SkillArrays
2454 //============================================================================
2455 function SkillArrays takes nothing returns integer
2456 local integer level = GetHeroLevelAI()
2457
2458 if level > max_hero_level then
2459 set max_hero_level = level
2460 endif
2461
2462 if GetHeroId() == hero_id then
2463 return skills1[level]
2464 elseif GetHeroId() == hero_id2 then
2465 return skills2[level]
2466 else
2467 return skills3[level]
2468 endif
2469 endfunction
2470
2471 //--------------------------------------------------------------------------------------------------
2472 // SetSkillArray
2473 //--------------------------------------------------------------------------------------------------
2474 function SetSkillArray takes integer index, integer id returns nothing
2475 local integer i = 1
2476
2477 if index == 1 then
2478 if hero_id != id then
2479 return
2480 endif
2481 loop
2482 set skills1[i] = skill[i]
2483 exitwhen i == 10
2484 set i = i + 1
2485 endloop
2486 elseif index == 2 then
2487 if hero_id2 != id then
2488 return
2489 endif
2490 loop
2491 set skills2[i] = skill[i]
2492 exitwhen i == 10
2493 set i = i + 1
2494 endloop
2495 else
2496 if hero_id3 != id then
2497 return
2498 endif
2499 loop
2500 set skills3[i] = skill[i]
2501 exitwhen i == 10
2502 set i = i + 1
2503 endloop
2504 endif
2505 endfunction
2506
2507 //============================================================================
2508 // AwaitMeleeHeroes
2509 //============================================================================
2510 function AwaitMeleeHeroes takes nothing returns nothing
2511 if GetUnitCountDone(hero_id2) > 0 then
2512 set two_heroes = true
2513 endif
2514 loop
2515 exitwhen GetUnitCountDone(hero_id)>0 and (take_exp or (not two_heroes or GetUnitCountDone(hero_id2)>0))
2516 call Sleep(1)
2517 endloop
2518 endfunction
2519
2520 //============================================================================
2521 // PickMeleeHero
2522 //============================================================================
2523 function PickMeleeHero takes race raceid returns integer
2524 local integer first
2525 local integer second
2526 local integer third
2527 local integer last
2528 local integer array heroes
2529
2530 //------------------------------------------------------------------------
2531 if raceid == RACE_HUMAN then
2532 //------------------------------------------------------------------------
2533 set heroes[1] = ARCHMAGE
2534 set heroes[2] = MTN_KING
2535 set heroes[3] = PALADIN
2536 set heroes[4] = BLOOD_MAGE
2537
2538 //------------------------------------------------------------------------
2539 elseif raceid == RACE_ORC then
2540 //------------------------------------------------------------------------
2541 set heroes[1] = BLADE_MASTER
2542 set heroes[2] = FAR_SEER
2543 set heroes[3] = TAUREN_CHIEF
2544 set heroes[4] = SHADOW_HUNTER
2545
2546 //------------------------------------------------------------------------
2547 elseif raceid == RACE_NIGHTELF then
2548 //------------------------------------------------------------------------
2549 set heroes[1] = DEMON_HUNTER
2550 set heroes[2] = KEEPER
2551 set heroes[3] = MOON_BABE
2552 set heroes[4] = WARDEN
2553
2554 //------------------------------------------------------------------------
2555 elseif raceid == RACE_UNDEAD then
2556 //------------------------------------------------------------------------
2557 set heroes[1] = DEATH_KNIGHT
2558 set heroes[2] = DREAD_LORD
2559 set heroes[3] = LICH
2560 set heroes[4] = CRYPT_LORD
2561 else
2562 set hero_id = 0
2563 endif
2564
2565 if VersionCompatible(VERSION_FROZEN_THRONE) then
2566 set last = 4
2567 else
2568 set last = 3
2569 endif
2570
2571 set first = GetRandomInt(1,last)
2572 set second = GetRandomInt(1,last-1)
2573 set third = GetRandomInt(1,last-2)
2574
2575 set hero_id = heroes[first]
2576 set heroes[first] = heroes[last]
2577 set hero_id2 = heroes[second]
2578 set heroes[second] = heroes[last-1]
2579 set hero_id3 = heroes[third]
2580
2581 return hero_id
2582 endfunction
2583